<template>
  <div class="mod-role">
    <el-container>
      <el-aside style="width: 65%">
        <el-card class="box-card">
          <template #header>
            <span class="r-title">角色列表</span>
          </template>
          <data-table ref="dataTableRef" name="role" :initLoad="true" url="/role/select">
            <!-- ------------------------------------------ 工具栏 ------------------------------------------ -->
            <template v-slot:toolbar>
              <el-button-group class="toolbar-btngroup">
                <el-button v-if="admin.isAuth('admin:role:save')" @click="() => saveOrUpdateEvent('add')" type="primary">
                  新增
                </el-button>
                <el-button v-if="admin.isAuth('admin:role:save')" @click="() => saveOrUpdateEvent('update')" type="warning">
                  修改
                </el-button>
                <el-button v-if="admin.isAuth('admin:role:delete')" @click="() => deleteEvent()" type="danger">
                  删除
                </el-button>
              </el-button-group>
            </template>
            <!-- ---------------------------------------- 数据表格列 ---------------------------------------- -->
            <el-table-column prop="code" header-align="center" align="center" label="角色代码" width="120" />
            <el-table-column prop="name" header-align="center" align="left" label="角色名称" width="160" />
            <el-table-column prop="description" show-overflow-tooltip header-align="center" label="备注" />
            <el-table-column fixed="right" header-align="center" align="center" width="180" label="操作">
              <template #default="scope">
                <el-button v-if="admin.isAuth('admin:role:permission')" size="small" @click="loadPermissionEvent(scope.row)">
                  权限
                </el-button>
              </template>
            </el-table-column>
          </data-table>
        </el-card>
      </el-aside>
      <el-main v-if="tree.show" style="padding: 0 20px; min-width: 400px">
        <el-card class="box-card">
          <template #header>
            <span class="r-title">角色[{{ selectData.name }}] - 权限管理</span>
          </template>
          <div style="padding-bottom: 10px;">
            <el-row :gutter="20" class="toolbar-box">
              <el-col :span="14">
                <el-input placeholder="输入关键字进行过滤" v-model="filterTreeText" />
              </el-col>
              <el-col :span="10">
                <el-button-group class="toolbar-btngroup fr">
                  <el-button v-if="admin.isAuth('admin:role:save-permission') && tree.enable" @click="() => selectAllEvent()" :disabled="tree.submitted">
                    <icon-svg :name="tree.sabicon"></icon-svg>
                  </el-button>
                  <el-button v-if="admin.isAuth('admin:role:save-permission') && tree.enable" @click="() => saveOrUpdatePermissionEvent()" :disabled="tree.submitted" type="danger">
                    <icon-svg name="save"></icon-svg>
                  </el-button>
                </el-button-group>
              </el-col>
            </el-row>
          </div>
          <div style="height: 480px">
            <el-scrollbar style="height: 100%">
              <el-tree node-key="id" class="filter-tree" :props="treeProps" :data="tree.data" empty-text="木有数据~"
                :default-checked-keys="tree.checkedKeys" show-checkbox check-on-click-node default-expand-all
                v-loading.lock="tree.loading" element-loading-text="拼命加载中" :filter-node-method="filterTreeNode"
                ref="treeRef">
                <template #default="{ node, data }">
                  <span class="custom-tree-node">
                    <icon-svg v-if="data.icon !== undefined && data.icon !== null" :name="data.icon"></icon-svg>
                    <span>{{ node.label }}</span>
                  </span>
                </template>
              </el-tree>
            </el-scrollbar>
          </div>
        </el-card>
      </el-main>
    </el-container>
    <!-- 弹窗, 新增 / 修改 -->
    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdateRef" @loadRoleTableData="loadRoleTableData" />
  </div>
</template>

<script lang="ts" setup>
import admin from "@/utils/admin";
import http from "@/utils/httpRequest";
import { ref, reactive, watch, nextTick } from "vue";
import cloneDeep from "lodash/cloneDeep";
import { ElTree, ElMessage, ElMessageBox } from "element-plus";

import AddOrUpdate from "./role-add-or-update.vue";

// 表格选中数据
const selectData = ref();

// 菜单树默认属性
const treeProps = ref({
  label: "name",
  children: "children",
});

// 资源树相关属性
const tree = reactive({
  // 树形结构
  data: [],
  // 是否显示
  show: false,
  // 加载状态
  loading: false,
  // 是否有权限修改
  enable: false,
  // 默认选中的数据，不包含半选节点
  checkedKeys: [],
  // 所有权限资源ID集合
  ids: [],
  // 新增资源权限ID集合
  addIds: [],
  // 删除资源权限ID集合
  deleteIds: [],
  // 是否在提交保存
  submitted: false,
  // 全选按钮的图标
  sabicon: "success",
});

// 菜单树过滤文本
const filterTreeText = ref("");

// 新增修改弹窗是否显示
const addOrUpdateVisible = ref(false);

// 资源树引用
const treeRef = ref<InstanceType<typeof ElTree>>();

// 监听查询内容变化
watch(filterTreeText, (n, o) => {
  treeRef.value!.filter(n);
});

// 数据表格引用
const dataTableRef = ref();

// 弹窗引用
const addOrUpdateRef = ref();

// 加载列表
const loadRoleTableData = () => {
  dataTableRef.value.loadTableData();
};

// 新增或者修改
const saveOrUpdateEvent = async (action) => {
  let data;
  if (action === "update") {
    data = admin.obtainOneSelectionTableData(dataTableRef.value);
    if (!data) {
      return;
    }
  }
  addOrUpdateVisible.value = true;
  await nextTick();
  addOrUpdateRef.value.initForm(action, data);
};

// 删除事件
const deleteEvent = () => {
  admin.batchDeleteSelectionTableData(dataTableRef.value, "/role/delete");
};

// 加载角色的权限树
const loadPermissionEvent = (data) => {
  selectData.value = data;
  tree.show = true;
  initPermissionData();
};

// 初始化权限数据
const initPermissionData = () => {
  tree.loading = true;
  http
    .post({
      url: `/role/permission?roleId=${selectData.value.id}`,
    })
    .then(({ data }) => {
      if (http.success(data) && data.body) {
        let body = data.body;
        tree.enable = body.enable === "Y";
        let checkedKeys = cloneDeep(body.ids);
        treeDataHandle(body.tree, checkedKeys, !tree.enable);
        tree.ids = body.ids;
        tree.checkedKeys = checkedKeys;
        tree.data = body.tree;
      }
      tree.loading = false;
    });
};

// 保存权限
const saveOrUpdatePermissionEvent = () => {
  if (tree.submitted) {
    return;
  }
  // 比较权限信息变化处理
  contrastPermissionHandle();
  // 如果没有修改则不进行处理
  if (tree.addIds.length === 0 && tree.deleteIds.length === 0) {
    ElMessage.info("您没有进行权限修改，不能进行提交操作！");
    return;
  }
  // 进行提交操作
  let tip = `本次操作角色[${selectData.value.name}]一共`;
  tip += tree.addIds.length > 0 ? `新增[${tree.addIds.length}]` : "";
  tip += tree.deleteIds.length > 0 ? `删除[${tree.deleteIds.length}]` : "";
  tip += "条资源，确认要进行保存吗?";
  ElMessageBox
    .confirm(tip, "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
    .then(() => {
      tree.submitted = true;
      http
        .post({
          url: '/role/save-permission',
          data: {
            roleId: selectData.value.id,
            addResourceIds: tree.addIds,
            deleteResourceIds: tree.deleteIds,
          },
        })
        .then(({ data }) => {
          if (http.success(data, true, true)) {
            initPermissionData();
          }
          tree.submitted = false;
        });
    })
    .catch(()=>{});
};

// 比较权限信息变化处理
const contrastPermissionHandle = () => {
  // 获取所有选中和半选中的id数组
  let checkedKeys = treeRef.value.getCheckedKeys().concat(treeRef.value.getHalfCheckedKeys());
  // 判断新增的ID
  tree.addIds = [];
  for (let i = 0; i < checkedKeys.length; i++) {
    if (tree.ids.indexOf(checkedKeys[i]) === -1) {
      tree.addIds.push(checkedKeys[i]);
    }
  }
  // 判断删除的ID
  tree.deleteIds = [];
  for (let i = 0; i < tree.ids.length; i++) {
    if (checkedKeys.indexOf(tree.ids[i]) === -1) {
      tree.deleteIds.push(tree.ids[i]);
    }
  }
};

// 树形结构数据追加禁用标志和移除半选中状态的选中ID
const treeDataHandle = (treeData, checkedKeys = [], disabled = true) => {
  for (let i = 0; i < treeData.length; i++) {
    let data = treeData[i];
    // 禁用状态设置
    data["disabled"] = disabled;
    if (data.children && data.children.length > 0) {
      // 处理子节点
      treeDataHandle(data.children, checkedKeys, disabled);
      // 默认选中数组处理，移除半选节点
      if (checkedKeys.indexOf(data.id) !== -1) {
        for (let d = 0; d < data.children.length; d++) {
          if (checkedKeys.indexOf(data.children[d].id) === -1) {
            delete checkedKeys[checkedKeys.indexOf(data.id)];
            break;
          }
        }
      }
    }
  }
};

// 全部选择事件
const selectAllEvent = () => {
  if (tree.sabicon === "success") {
    treeRef.value.setCheckedNodes(tree.data);
    tree.sabicon = "success-fill";
  } else {
    treeRef.value.setCheckedNodes([]);
    tree.sabicon = "success";
  }
};

// 过滤菜单
const filterTreeNode = (value, data) => {
  if (!value) {
    return true;
  }
  return data.name.indexOf(value) !== -1;
};
</script>

<style lang="scss" scoped>
.mod-role {

  .r-title {
    font-size: 16px;
    font-weight: 600;
  }
}
</style>